/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package GoogleApiPort;

import DataTypes.GoogleApiDataTypes.Address;
import com.google.api.client.googleapis.GoogleHeaders;
import com.google.api.client.http.*;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.http.json.JsonHttpParser;
import com.google.api.client.json.jackson.JacksonFactory;
import java.io.IOException;
import java.util.Iterator;

/**
 *
 * @author thang
 */
public class GpsDecoder {
    private static final String PLACES_SEARCH_URL =  "https://maps.googleapis.com/maps/api/place/search/json?";
    private static final String PLACES_DETAILS_URL =  "https://maps.googleapis.com/maps/api/place/details/json?";
    private static final String REVERSE_GEOCODING_URL =  "http://maps.googleapis.com/maps/api/geocode/json?";
    private static final boolean PRINT_AS_STRING = false;
    private static final String API_KEY = "AIzaSyDYwyu-45grd2tSbAbzJZ0ogY2cxFLvvxQ";
    
    public static final int MAX_PLACE_QUERY_TIMES = 6;
    
    private static int  mRadius = 500;
    
    /*
     * from lat and long return a list of known place arround
     */
    public static DataTypes.GoogleApiDataTypes.PlacesList getPlacesList(double latitude, double longitude, int radius) throws IOException {
        DataTypes.GoogleApiDataTypes.PlacesList list = null;
        //String myUrl = "https://maps.googleapis.com/maps/api/place/search/json?location=-33.8670522,151.1957362&radius=500&types=food&name=harbour&sensor=false&key=AIzaSyDYwyu-45grd2tSbAbzJZ0ogY2cxFLvvxQ";
       
        //System.out.println("Perform Search ....");
        //System.out.println("-------------------");

        // set up the HTTP request factory
        HttpTransport transport = new NetHttpTransport();
        HttpRequestFactory httpRequestFactory = transport.createRequestFactory(new HttpRequestInitializer() {
            @Override
            public void initialize(HttpRequest request) {
                // set the parser
                //JsonHttpParser parser = new JsonHttpParser();
                JsonHttpParser parser = new JsonHttpParser();
                //JsonCParser parser = new JsonCParser();     //
                parser.jsonFactory = new JacksonFactory();
                request.addParser(parser);                  //
                // set up the Google headers
                GoogleHeaders headers = new GoogleHeaders();   //
                headers.setApplicationName("Place API test");   //
                headers.gdataVersion = "2";
                request.setHeaders(headers);
            }
        });

        try {
            HttpRequest request = httpRequestFactory.buildGetRequest(new GenericUrl(PLACES_SEARCH_URL));
            request.getUrl().put("key", API_KEY);
            request.getUrl().put("location", latitude + "," + longitude);
            request.getUrl().put("radius", radius);
            request.getUrl().put("sensor", "false");
            //request.url.put("types", "food");
            
            list = request.execute().parseAs(DataTypes.GoogleApiDataTypes.PlacesList.class);
            /*
            if (PRINT_AS_STRING) {
                //System.out.println(request.execute().parseAsString());
            } else {
                //list = request.execute().parseAs(PlacesList.class);
                //System.out.println(place);
                System.out.println("STATUS = " + list.status);
                for (GoogleApiDataTypes.Place place : list.results) {
                    System.out.println();
                    System.out.println("Place ID: " + place.id);
//                    System.out.println("Place name: " + place.name);
//                    System.out.println("Place reference: " + place.reference);
                }
            }
            */
            
        } catch (HttpResponseException e) {
           System.err.println(e.getResponse().parseAsString());
           throw e;
        }
        
        return list;
    }
    
    /*
     * from a placeReference (place ID of google) get its address
     */
    public static DataTypes.GoogleApiDataTypes.Address getPlaceAddress(String placeReference) throws IOException {
        DataTypes.GoogleApiDataTypes.DetailsList list = null;
        DataTypes.GoogleApiDataTypes.Address address = null; 
        //String myUrl = "https://maps.googleapis.com/maps/api/place/details/json?reference=CnRjAAAAD1pLO2U7ZLFy-krLdRi4bNZzL36Q22zF3DQU8jn1qavhd8JGGGkOacIhm-b6vzj1jMP6Dy-10OEe1IXidNfUHvV4iiO6NO6lbdHDgaNTYNG1Qw2vh5bVTnmw2UaUe1zVzbTsa9AqHi0xObYGrPCzJRIQRlHB8pbUoNgF7Eh-W7-2dxoU8YbU7rl1p6qxdAAouEsAVj1YGLY&sensor=true&key=AIzaSyDYwyu-45grd2tSbAbzJZ0ogY2cxFLvvxQ";
       
        //System.out.println("Perform Search ....");
        //System.out.println("-------------------");

        // set up the HTTP request factory
        HttpTransport transport = new NetHttpTransport();
        HttpRequestFactory httpRequestFactory = transport.createRequestFactory(new HttpRequestInitializer() {
            @Override
            public void initialize(HttpRequest request) {
                // set the parser
                //JsonHttpParser parser = new JsonHttpParser();
                JsonHttpParser parser = new JsonHttpParser();
                //JsonCParser parser = new JsonCParser();     //
                parser.jsonFactory = new JacksonFactory();
                request.addParser(parser);                  //
                // set up the Google headers
                GoogleHeaders headers = new GoogleHeaders();   //
                headers.setApplicationName("Place Details");   //
                headers.gdataVersion = "1";
                request.setHeaders(headers);
            }
        });

        try {
            HttpRequest request = httpRequestFactory.buildGetRequest(new GenericUrl(PLACES_DETAILS_URL));
            
            request.getUrl().put("reference", placeReference);
            request.getUrl().put("sensor", "false");
            request.getUrl().put("key", API_KEY);
            
            list = request.execute().parseAs(DataTypes.GoogleApiDataTypes.DetailsList.class);
            
            if( list.status.equalsIgnoreCase(DataTypes.GoogleApiDataTypes.Status.OK.toString()) ){
                address = new DataTypes.GoogleApiDataTypes.Address();
                address.types = list.result.types;
                address.formatted_address = list.result.formatted_address;
                address.address_components = list.result.address_components;
                address.geometry = list.result.geometry;
            }

            /*
            if (PRINT_AS_STRING) {
                //System.out.println(request.execute().parseAsString());
            } else {
                //list = request.execute().parseAs(PlacesList.class);
                //System.out.println(place);
                System.out.println("STATUS = " + list.status);
                System.out.println();
                System.out.println("Formatted address from list: " + list.result.formatted_address);
                System.out.println("Formatted address from address: " + address.formatted_address);
            }
            */
            
        } catch (HttpResponseException e) {
           System.err.println(e.getResponse().parseAsString());
           throw e;
        }
        return address;
    }
    
    /*
     * from lat and log return the most detail address
     */
    public static DataTypes.GoogleApiDataTypes.Address getGpsDataAddress(double latitude, double longitude) throws IOException{
        // get addres_list
        DataTypes.GoogleApiDataTypes.AddressList list = reverseGeocoding(latitude, longitude);

        // get the most detail one (the first one)
        DataTypes.GoogleApiDataTypes.Address address = null;
        if ( (list != null) && list.status.equalsIgnoreCase(DataTypes.GoogleApiDataTypes.Status.OK.toString()) ){
            for (Iterator<Address> it = list.results.iterator(); it.hasNext();) {
                address = it.next();
                break;
            }
        }        
        return address;
    }

    
    // from lat and long return list of address from detail to more common
    public static DataTypes.GoogleApiDataTypes.AddressList reverseGeocoding(double latitude, double longitude) throws IOException {
        DataTypes.GoogleApiDataTypes.AddressList list = null;
        //String reverseUrl = "http://maps.googleapis.com/maps/api/geocode/json?latlng=-37.8408040199429,144.932704623789&sensor=false";
       
        //System.out.println("Perform Search ....");
        //System.out.println("-------------------");

        // set up the HTTP request factory
        HttpTransport transport = new NetHttpTransport();
        //HttpRequestFactory httpRequestFactory = transport.createRequestFactory(); 
            
        HttpRequestFactory httpRequestFactory = transport.createRequestFactory(new HttpRequestInitializer() {
            @Override
            public void initialize(HttpRequest request) {
                // set the parser
                //JsonHttpParser parser = new JsonHttpParser();
                JsonHttpParser parser = new JsonHttpParser();
                //JsonCParser parser = new JsonCParser();     //
                parser.jsonFactory = new JacksonFactory();
                request.addParser(parser);                  //
                // set up the Google headers
                GoogleHeaders headers = new GoogleHeaders();   //
                headers.setApplicationName("Google API Reverse Geocoding");   //
                headers.gdataVersion = "1";
                request.setHeaders(headers); //.headers = headers;                      //
            }
        });

        try {
            HttpRequest request = httpRequestFactory.buildGetRequest(new GenericUrl(REVERSE_GEOCODING_URL));
            request.getUrl().put("latlng", latitude + "," + longitude); //.url.put("latlng", latitude + "," + longitude);
            request.getUrl().put("sensor", "false"); //.url.put("sensor", "false");

            //System.out.println(request.execute().parseAsString());
            //System.out.println(request.getUrl());
            //System.out.println(GoogleApiDataTypes.Status.OK.toString());
            
            list = request.execute().parseAs(DataTypes.GoogleApiDataTypes.AddressList.class);

            /*
            if (PRINT_AS_STRING) {
                //System.out.println(request.execute().parseAsString());
            } else {
                //list = request.execute().parseAs(PlacesList.class);
                //System.out.println(place);
                System.out.println("STATUS = " + list.status);
                if ( list.status.equalsIgnoreCase(GoogleApiDataTypes.Status.OK.toString()) ){
                    for (GoogleApiDatanhaTypes.Address address : list.results) {
                        System.out.println(buildSqlCommandAddress(address, 2, 1));
                        //System.out.println();
                        //System.out.println("Formated Address: " + address.formatted_address);
                    }
                }
            }
            */
            
        } catch (HttpResponseException e) {
           System.err.println(e.getResponse().parseAsString());
           throw e;
        }
        
        return list;
    }
    
}
